/*
    The MIT License

    Copyright (c) 2010 IFMO/GameDev Studio

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
*/


#pragma once

/*-----------------------------------------------------------------------------
	Core external stuff :
-----------------------------------------------------------------------------*/

#pragma warning (disable : 4996)	//	'function' : was declared deprecated
#pragma warning (disable : 4800)	//	warning C4800: 'int' : forcing value to bool 'true' or 'false' 
#pragma warning (disable : 4244)	//	warning C4244: '=' : conversion from 'lua_Number' to 'int', possible 

/*-----------------------------------------------------------------------------
	Data types :
-----------------------------------------------------------------------------*/

#include "..\types.h"

/*-----------------------------------------------------------------------------
	DLL linking stuff :
-----------------------------------------------------------------------------*/

#undef DLL_EXPORT
#undef DLL_IMPOR
#ifdef _WIN32 
    #define DLL_EXPORT  extern "C"  __declspec(dllexport)
    #define DLL_IMPORT  extern "C"  __declspec(dllimport)
#else
    #define DLL_EXPORT
    #define DLL_IMPORT
#endif


#ifdef STATIC_CORE
	#define CORE_API
#else
	#ifdef CORE_EXPORTS
		#define CORE_API  __declspec(dllexport)
	#else
		#define CORE_API  __declspec(dllimport)
	#endif
#endif

/*-----------------------------------------------------------------------------
	Common 3-rd party includes :
-----------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <math.h>

#include <string>
#include <vector>

extern "C" {
    #include "../core/lua/src/lua.h"
    #include "../core/lua/src/lualib.h"
    #include "../core/lua/src/lauxlib.h"
}

#include "rapidxml/rapidxml.hpp"
#include "rapidxml/rapidxml_ext.hpp"

/*-----------------------------------------------------------------------------
	Assertions :
-----------------------------------------------------------------------------*/

#undef ASSERT
#undef VERIFY
#undef SIGNAL
#undef FATAL
#undef ASSERT_SLOW
#undef VERIFY_SLOW

#define	ASSERT(expr)	if (!(expr))	CoreAssert(#expr, __FUNCTION__, __FILE__, __LINE__);
#define VERIFY(expr)	if (!(expr))	CoreAssert(#expr, __FUNCTION__, __FILE__, __LINE__);
#define	SIGNAL(msg)		CoreSignal	(msg, __FUNCTION__, __FILE__, __LINE__);
#define	FATAL(msg)		CoreFatal	(msg, __FUNCTION__, __FILE__, __LINE__);

#include "core_errors.h"
#define	RUNTIME_ERROR(dscr)	throw runtime_error((const char*)dscr);	

#define NOT_IMPLEMENTED	SIGNAL("Not implemented")

/*-----------------------------------------------------------------------------
	Core functions :
-----------------------------------------------------------------------------*/

#include "hard_ref.hpp"
#include "weak_ref.hpp"

class	ICoreApp			;
class	ICoreObject			;
class	ILog				;
class	ISystem				;
class	IFileSystem			;
class	IAtoms				;
class	IGeometryFactory	;
class	IImageFactory		;
class	IConfig				;
class	IInputSystem		;
class	IUserInterface		;
class	IBlob				;

class	ILinker				;

class	IRenderSystem		;
class	ISoundSystem		;
class	IPhysics			;
class	IGame				;

CORE_API	bool				CoreRunApp			( ICoreApp *app );
CORE_API	void				CoreQuit			( void );
CORE_API	void				CoreRestart			( void );
CORE_API	const char		*	CoreVersion			( void );
CORE_API	uint				CoreFrameCount		( void );
CORE_API	void				CoreIncFrameCount	( void );

CORE_API	lua_State		*	CoreLua					( void );
CORE_API	void				CoreExecuteFile			( const char *path, bool throw_exception=false );
CORE_API	void				CoreExecuteString		( const char *command, bool throw_exception=false );
CORE_API	void				CoreExecuteFileUser		( const char *path, bool throw_exception=false );
CORE_API	void				CoreExecuteStringUser	( const char *command, bool throw_exception=false );

CORE_API	void				CoreAssert			( const char *expr, const char *func, const char *file, uint line );
CORE_API	void				CoreSignal			( const char *expr, const char *func, const char *file, uint line );
CORE_API	void				CoreFatal			( const char *expr, const char *func, const char *file, uint line );


/*-----------------------------------------------------------------------------
    Console macros :
-----------------------------------------------------------------------------*/

#define LOGF(frmt, ...)				Log()->LogMessage(LOG_MSG_INFO,			__FILE__,__LINE__, frmt, __VA_ARGS__)
#define LOG_WARNING(frmt, ...)		Log()->LogMessage(LOG_MSG_WARNING,		__FILE__,__LINE__, frmt, __VA_ARGS__)
#define LOG_ERROR(frmt, ...)		Log()->LogMessage(LOG_MSG_ERROR,		__FILE__,__LINE__, frmt, __VA_ARGS__)
#define LOG_FATAL(frmt, ...)		Log()->LogMessage(LOG_MSG_FATAL,		__FILE__,__LINE__, frmt, __VA_ARGS__)
#define LOG_DEBUG(frmt, ...)		Log()->LogMessage(LOG_MSG_DEBUG,		__FILE__,__LINE__, frmt, __VA_ARGS__)
#define LOGD(frmt, ...)				Log()->LogMessage(LOG_MSG_DEBUG,		__FILE__,__LINE__, frmt, __VA_ARGS__)
#define LOG_SCRIPT(frmt, ...)		Log()->LogMessage(LOG_MSG_SCRIPT,		__FILE__,__LINE__, frmt, __VA_ARGS__)

#define LOG_INIT(s)					Log()->LogMessage(LOG_MSG_INFO,			__FILE__,__LINE__, "INIT : %s", s)
#define LOG_SHUTDOWN(s)				Log()->LogMessage(LOG_MSG_INFO,			__FILE__,__LINE__, "SHUTDOWN : %s", s)
#define LOG_SPLIT(headline)			Log()->LogSplit(headline);

#define DEBUG_STRING(frmt, ...)		Log()->AddDebugString(frmt, __VA_ARGS__)

/*-----------------------------------------------------------------------------
	Includes :
-----------------------------------------------------------------------------*/

#include "math/math.h"
#include "string/string.h"

#include "../interfaces/int_core.h"

#include "lua_ext.h"
#include "lua_guard.h"
#include "lua_interface.h"

CORE_API	ILog				*	Log					( void );
CORE_API	ISystem				*	System				( void );
CORE_API	ILinker				*	Linker				( void );
CORE_API	IFileSystem			*	FileSystem			( void );
CORE_API	IAtoms				*	Atoms				( void );
CORE_API	IGeometryFactory	*	Geometry			( void );
CORE_API	IImageFactory		*	ImageFactory		( void );
CORE_API	IConfig				*	Config				( void );
CORE_API	IInputSystem		*	InputSystem			( void );
CORE_API	IUserInterface		*	UserInterface		( void );

CORE_API	IBlob				*	CoreCreateBlob		( uint size );

inline ISystem					*	sys	( void ) { return System();		}
inline IFileSystem				*	fs	( void ) { return FileSystem(); }
inline IGeometryFactory			*	ge	( void ) { return Geometry();	}
inline IImageFactory			*	ifct( void ) { return ImageFactory(); }
inline IRenderSystem			*	rs	( void ) { return Linker()->RenderSystem(); }
inline ISoundSystem				*	ss	( void ) { return Linker()->SoundSystem	(); }
inline IPhysics					*	phys( void ) { return Linker()->Physics	(); }
inline IGame					*	game( void ) { return Linker()->Game		(); }

/*-----------------------------------------------------------------------------
	Function profiler :
-----------------------------------------------------------------------------*/

class EFuncProfiler {
	public:
		EFuncProfiler	( const char *func, const char *text ) {
			this->func	=	func;
			this->text	=	text;
			msec = sys()->MSecRDTSC();
		}
		~EFuncProfiler	( void ) {
			double msec2 = sys()->MSecRDTSC();
			double time  = msec2 - msec;
			DEBUG_STRING("PROF: %s() : %s : %15.8f msec", func, text, time);
		}
	private:
		const char	*func;
		const char	*text;
		double		msec;
	};
	
#define PROFILE_FUNCTION(s)	EFuncProfiler	__func_prof__(__FUNCTION__, s)	

